package com.csi.service.impl;

import com.csi.domain.UserBook;
import com.csi.mapper.UserBookMapper;
import com.csi.service.UserBookService;
import com.csi.utils.JsonResult;
import com.csi.utils.ReturnResults;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;

@Service
public class UserBookServiceImpl implements UserBookService {

    @Autowired
    private UserBookMapper userBookMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private RabbitTemplate rabbitTemplate;


    private ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);
    private ConcurrentHashMap<UserBook, ScheduledFuture<?>> scheduledFutures = new ConcurrentHashMap<>();

    /**
     * 添加订单(用户可选多个房间)
     * @param userId
     * @param checkTime
     * @param leaveTime
     * @param roomNum
     * @param price
     * @param phone
     * @param hotelId
     * @param roomTypeId
     * @return
     */
    @Override
    @Transactional
    public int saveBook(long userId, String checkTime, String leaveTime, int roomNum, double price, String phone, long hotelId, long roomTypeId) {
        List<Long> rooms = userBookMapper.findRoomId(roomTypeId,checkTime,leaveTime);

        List<UserBook> books = new ArrayList<>();
        if (rooms.size()<roomNum){
            return -1;
        }
        for(int i=0;i<roomNum;i++){
            UserBook userBook = new UserBook();
            userBook.setRoomId(rooms.get(i));
            userBook.setPhone(phone);
            userBook.setHotelId(hotelId);
            userBook.setPayStatus("待支付");

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Timestamp check = null;
            Timestamp leave = null;
            try {
                Date date = sdf.parse(checkTime);
                check = new Timestamp(date.getTime());

                Date date1 = sdf.parse(leaveTime);
                leave = new Timestamp(date1.getTime());
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }

            userBook.setCheckTime(check);
            userBook.setLeaveTime(leave);
            userBook.setBookPrice(BigDecimal.valueOf(price));
            userBook.setUserId(userId);
            books.add(userBook);
        }
        //给每一个房间生成订单,同时这个房价归属于userid
        int result = userBookMapper.saveBook(books);


        //同时房型剩余量如果小于等于3就将数量放入redis中(根据传进来的酒店的id和房型id去进行判断)
        int numCount = userBookMapper.findRoomNum(roomTypeId, checkTime, leaveTime);
        //如果这个数量小于等于3就放入redis中
        if(numCount<=3){
            // 将结果存入 Map
            ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
            ops.set("roomTypeId:"+roomTypeId, String.valueOf(numCount));
        }

        //redis中的存储方式：酒店id：房型id，数量


        //同时需要去锁住预订房间数量
//        int delete  = userBookMapper.deleteRoomNum(roomNum,roomTypeId);
        //定时取消预订
        scheduleUnlockTask(userId,checkTime,leaveTime,price,phone,hotelId,roomNum,roomTypeId,books);


        return result;
    }





    @Transactional
    public void scheduleUnlockTask(long userId, String checkTime, String leaveTime, double price, String phone, long hotelId, int roomNum, long roomTypeId, List<UserBook> books){
        long delay = 30*1000;

        UserBook userBook = new UserBook();

        ScheduledFuture<?> future = scheduledExecutorService.schedule(() ->{
            userBook.setUserId(userId);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date date = null;
            try {
                date = sdf.parse(checkTime);
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
            Timestamp check = new Timestamp(date.getTime());

            Date date1 = null;
            try {
                date1 = sdf.parse(leaveTime);
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
            Timestamp leave = new Timestamp(date1.getTime());

            userBook.setCheckTime(check);
            userBook.setLeaveTime(leave);
            userBook.setPhone(phone);
            userBook.setBookPrice(BigDecimal.valueOf(price));
            userBook.setHotelId(hotelId);

            //拿到订单列表查看支付状态,如果支付状态是已支付则不撤回,如果是待支付则取消订单
            for (UserBook book : books) {
                List<String> payStatus = userBookMapper.findPayStatusById(book);
                for (String status : payStatus) {
                    if ("待支付".equals(status)){
                        //取消订单
                        int updated2 = userBookMapper.cancel(userBook);
                    }
                }

            }
        },delay, TimeUnit.MILLISECONDS);

        scheduledFutures.put(userBook, future);
    }

    /**
     * 定时任务：每天凌晨1点检查并更新预订状态。
     */
    @Scheduled(cron = "0 0 1 * * ?") // 每天凌晨1点执行
    public void checkAndUpdateBookingStatus() {
        List<UserBook> bookings = userBookMapper.findByStatus("待入住");

        Date now = new Date();

        for (UserBook booking : bookings) {
            if (now.after(booking.getCheckTime()) && now.before(booking.getLeaveTime())) {
                booking.setPayStatus("入住中");
            } else if (!now.before(booking.getLeaveTime())) {
                booking.setPayStatus("待评价");
            }
            userBookMapper.updateStatues(booking); // 保存更新后的状态
        }
    }

    /**
     * 用户支付
     * @param userBook
     * @return
     */
    @Override
    public int payment(UserBook userBook) {

        int result = userBookMapper.payment(userBook);

        ScheduledFuture<?> future = scheduledFutures.get(userBook);
        if(future!=null){
            future.cancel(true);
            scheduledFutures.remove(userBook);
        }
        return result;
    }


    /**
     * 已完成
     * @param bookId
     * @return
     */
    @Override
    public int completed(long bookId) {
        return userBookMapper.completed(bookId);
    }

    /**
     * 待评价
     * @param bookId
     * @return
     */
    @Override
    public int evaluated(long bookId) {
        return userBookMapper.evaluated(bookId);
    }

    /**
     * 根据入住日、离店日、房型模糊查询可订几间房
     * @param roomId
     * @param check_time
     * @param leave_time
     * @return
     */
    @Override
    public int findRoomNum(int roomId, String check_time, String leave_time) {
        return userBookMapper.findRoomNum(roomId, check_time, leave_time);
    }



    @Scheduled(cron = "0 0 18 * * ?") // 每天下午6点执行
    public void updateValueInRedis(){
        //先查询所有酒店
        //再查询


    }



    /**
     * 秒杀
     * @param userId
     * @param checkTime
     * @param leaveTime
     * @param roomNum
     * @param bookPrice
     * @param phone
     * @param hotelId
     * @param roomTypeId
     * @return
     */
    @Override
    public Object sec(long userId, String checkTime, String leaveTime, int roomNum, double bookPrice, String phone, long hotelId, long roomTypeId) {
        //加锁,防止多线程并发
        synchronized (UserBookServiceImpl.class){
            //预扣库存
            ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();

            Long res = ops.decrement("roomTypeId:" + roomTypeId, roomNum);
            if(res>=0){
                System.out.println("秒杀成功！");
                //发送消息(先生成订单)
                List<Long> rooms = userBookMapper.findRoomId(roomTypeId,checkTime,leaveTime);

                List<UserBook> books = new ArrayList<>();//一间房对应着一个订单，将订单列表发送给消息队列
                if (rooms.size()<roomNum){
                    return -1;
                }
                for(int i=0;i<roomNum;i++){
                    UserBook userBook = new UserBook();

                    userBook.setRoomId(rooms.get(i));
                    userBook.setPhone(phone);
                    userBook.setHotelId(hotelId);
                    userBook.setPayStatus("待支付");

                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                    Timestamp check = null;
                    Timestamp leave = null;
                    try {
                        Date date = sdf.parse(checkTime);
                        check = new Timestamp(date.getTime());
                        Date date1 = sdf.parse(leaveTime);
                        leave = new Timestamp(date1.getTime());
                    } catch (ParseException e) {
                        throw new RuntimeException(e);
                    }
                    userBook.setCheckTime(check);
                    userBook.setLeaveTime(leave);
                    userBook.setBookPrice(BigDecimal.valueOf(bookPrice));
                    userBook.setUserId(userId);
                    books.add(userBook);
                }
                rabbitTemplate.convertAndSend("order.queue",books);
                //定时取消预订
                scheduleUnlockTask(userId,checkTime,leaveTime,bookPrice,phone,hotelId,roomNum,roomTypeId,books);

                return new JsonResult<>(ReturnResults.ACCESS_SUCCESS,"秒杀成功！");
            }else {
                return new JsonResult<>(ReturnResults.ACCESS_FAILED,"房间已满！");
            }
        }

    }





}
